home *** CD-ROM | disk | FTP | other *** search
/ PC-Blue - MS DOS Public Domain Library / PC-Blue MS-DOS Public Domain Library - NYACC.iso / vol194 / kermasm.arc / MSXIBM.ASM < prev    next >
Encoding:
Assembly Source File  |  1985-11-14  |  22.0 KB  |  856 lines

  1. ; Kermit system dependent module for IBM-PC
  2.  
  3. ; Edit History
  4. ;  Make break be 275 ms, DT 5:51pm  Thursday, 6 December 1984
  5.  
  6.     public    serini, serrst, clrbuf, outchr, coms, vts, dodel,
  7.     public    ctlu, cmblnk, locate, prtchr, dobaud, clearl,
  8.     public    dodisk, getbaud, beep,
  9.     public    count, xofsnt, puthlp, putmod, clrmod, poscur
  10.     public    sendbr, machnam, setktab, setkhlp, lclini, showkey
  11.     include msdefs.h
  12.  
  13. false    equ    0
  14. true    equ    1
  15. mntrgh    equ    bufsiz*3/4    ; High point = 3/4 of buffer full.
  16.  
  17. ; constants used by serial port handler
  18.  
  19. BRKBIT    EQU    040H        ; Send-break bit. 
  20. TIMER    EQU    40H        ; Use to issue short beep.
  21. PORT_B    EQU    61H        ; Port B address.
  22. MCONF    EQU    11H        ; Machine configuration. 
  23. KEYB    EQU    16H
  24. BIOS    EQU    10H
  25.  
  26. MDMDAT1    EQU    03F8H        ; Address of modem port (data). [19b]
  27. MDMSTS1    EQU    03FDH        ; Address of modem port    status. [19b]
  28. MDMCOM1    EQU    03FBH        ; Address of modem port command. [19b]
  29. MDMDAT2    EQU    02F8H        ; Port 2 address. [19b]
  30. MDMSTS2    EQU    02FDH        ; Port 2 status. [19b]
  31. MDMCOM2    EQU    02FBH        ; Port 2 command. [19b]
  32. MDMINP    EQU    1        ; Input ready bit.
  33.  
  34. MDMINTV    EQU    0030H        ; Address of modem port interrupt vector.
  35. MDINTV2 EQU    002CH        ; Address for port 2. [19b] 
  36. MDMINTO    EQU    0EFH        ; Mask to enable interrupt for modem port.
  37. MDINTO2 EQU    0F7H        ; Enable interrupt level 3. [19b]
  38. MDMINTC    EQU    010H        ; Bit to set to disable interrupts for modem.
  39. MDINTC2 EQU    008H        ; Disable IRQ3. [19b]
  40.  
  41. INTCONT    EQU    0021H        ; Address of 8259 interrupt controller ICW2-3.
  42. INTCON1    EQU    0020H        ; Address of 8259 ICW1.
  43. EOICOM    EQU    0064H        ; End of interrupt.
  44. EOICOM2    EQU    0063H        ; End of interrupt for COM2. [19b]
  45.  
  46. ; external variables used:
  47. ; drives - # of disk drives on system
  48. ; flags - global flags as per flginfo structure defined in pcdefs
  49. ; trans - global transmission parameters, trinfo struct defined in pcdefs
  50. ; portval - pointer to current portinfo structure (currently either port1
  51. ;    or port2)
  52. ; port1, port2 - portinfo structures for the corresponding ports
  53.  
  54. ; global variables defined in this module:
  55. ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
  56. ; setktab - keyword table for redefining keys (should contain a 0 if
  57. ;    not implemented)
  58. ; setkhlp - help for setktab.
  59.  
  60. datas     segment    public 'datas'
  61.     extrn    drives:byte,flags:byte, trans:byte
  62.     extrn    portval:word, port1:byte, port2:byte
  63.  
  64. setktab    db    12
  65.     mkeyw    'BACKSPACE',0eh
  66.     mkeyw    'F1',3bh
  67.     mkeyw    'F2',3ch
  68.     mkeyw    'F3',3dh
  69.     mkeyw    'F4',3eh
  70.     mkeyw    'F5',3fh
  71.     mkeyw    'F6',40h
  72.     mkeyw    'F7',41h
  73.     mkeyw    'F8',42h
  74.     mkeyw    'F9',43h
  75.     mkeyw    'F10',44h
  76.     mkeyw    'SCAN',-1
  77.  
  78. setkhlp    db    cr,lf,'Keyname: backspace, f1, ... f10, or "SCAN" follwed by '
  79.     db    'decimal scan code$'
  80. brkval    db    0        ; What to send for a break.
  81. brkadr    dw    0        ; Where to send it.
  82. modem    mdminfo    <MDMDAT1,MDMSTS1,MDMCOM1,MDMINTO,MDMINTC,EOICOM,MDMINTV>
  83. erms20    db    cr,lf,'?Warning: System has no disk drives$' ; [21a]
  84. erms40    db    cr,lf,'?Warning: Unrecognized baud rate$'
  85. badbd    db    cr,lf,'Unimplemented baud rate$'
  86. machnam    db    'IBM-PC$'
  87. crlf    db    cr,lf,'$'
  88. delstr  db    BS,BS,'  ',BS,BS,'$'     ; Delete string. [21d]
  89. clrlin  db    cr,'$'            ; Clear line (just the cr part).
  90. savsci    dw    ?        ; Save for serial port interrupt vector. [14]
  91. savscs    dw    ?        ; Ditto.  [14]  
  92. savbr1    dw    ?        ; "Break" interrupt vector. [25]
  93. savbr2    dw    ?        ; Ditto. [25]
  94. portin    db    0        ; Has comm port been initialized. [21c]
  95. xofsnt    db    0        ; Say if we sent an XOFF.
  96. xofrcv    db    0        ; Say if we received an XOFF.
  97. tmp    db    ?,'$'
  98. temp    dw    0
  99. temp1    dw    ?        ; Temporary storage.
  100. temp2    dw    ?        ; Temporary storage.
  101.  
  102. ontab    db    02H        ; Two entries.
  103.     db    03H,'OFF$'    ; Should be alphabetized.  [19a]
  104.     dw    00H
  105.     db    02H,'ON$'
  106.     dw    01H
  107.  
  108. comptab    db    04H
  109.     db    01H,'1$'
  110.     dw    01H
  111.     db    01H,'2$'
  112.     dw    00H
  113.     db    04H,'COM1$'
  114.     dw    01H
  115.      db    04H,'COM2$'
  116.     dw    00H
  117.  
  118. ; this table is indexed by the baud rate definitions given in
  119. ; pcdefs.  Unsupported baud rates should contain FF.
  120. bddat    label    word
  121.     dw    0FFH        ; 45.5 baud  -- Not supported.
  122.     dw    900H        ; 50 baud
  123.     dw    600H        ; 75 baud
  124.     dw    417H        ; 110 baud
  125.     dw    359H        ; 134.5 baud
  126.     dw    300H        ; 150 baud
  127.     dw    180H        ; 300 baud
  128.     dw    0C0H        ; 600 baud
  129.     dw    60H        ; 1200 baud
  130.     dw    40H        ; 1800 baud
  131.     dw    3AH        ; 2000 baud
  132.     dw    30H        ; 2400 baud
  133.     dw    18H        ; 4800 baud
  134.     dw    0CH        ; 9600 baud
  135.     dw    06H        ; 19200 baud
  136.     dw    03H        ; 38400 baud
  137.  
  138. ; variables for serial interrupt handler
  139.  
  140. source    db    bufsiz DUP(?)    ; Buffer for data from port.
  141. srcpnt    dw    0        ; Pointer in buffer (DI).
  142. count    dw    0        ; Number of chars in int buffer.
  143. savesi    dw    0        ; Save SI register here.    
  144. telflg    db    0        ; Are we acting as a terminal.
  145. mst    dw    0        ; Modem status address.
  146. mdat    dw    0        ; Modem data address.
  147. mdeoi    db    0        ; End-of-Interrupt value.
  148.  
  149. rbtrn    db    7fH        ; rubout
  150.  
  151. shkbuf    db    300 dup (?)    ; room for definition
  152. shkmsg    db    '  Scan code: '
  153. shkmln    equ    $-shkmsg
  154. shkms1    db    cr,lf,'  Definition: '
  155. shkm1ln    equ    $-shkms1
  156. datas    ends
  157.  
  158. code    segment    public
  159.     extrn    comnd:near, dopar:near, defkey:near, gss:near, lclyini:near
  160.     extrn    sleep:near
  161.     assume    cs:code,ds:datas
  162.  
  163. ; local initialization
  164.  
  165. lclini    proc    near
  166.     mov    ax,0eH        ; scan code for arrow key
  167.     mov    si,offset rbtrn    ; translate to rubout
  168.     mov    cx,1        ; one char translation
  169.     call    defkey
  170.     mov    brkval,BRKBIT    ; What to send for a break.
  171.     mov    ax,modem.mdcom    ; Where to send it.
  172.     mov    brkadr,ax
  173.     call    lclyini        ; let other module initialize too...
  174.     ret
  175. lclini    endp
  176.  
  177. ; this is called by Kermit initialization.  It checks the
  178. ; number of disks on the system, sets the drives variable
  179. ; appropriately.  Returns normally.  
  180.  
  181. DODISK    PROC    NEAR
  182.     int mconf            ; Get equipment configuration.
  183.     mov ah,al            ; Store AL value for a bit.
  184.     and al,01H            ; First, look at bit 0.
  185.     jz dodsk0            ; No disk drives -- forget it.
  186.     mov al,ah            ; Get back original value.
  187.     mov cl,6            ; Shift over bits 6 and 7.
  188.     shr al,cl            ; To positions 0 and 1.
  189.     inc al                ; Want 1 thru 4 (not 0 thru 3).
  190.     mov drives,al            ; Remember how many. 
  191.     ret
  192. dodsk0:    mov ah,prstr            ; Print a warning message.
  193.     mov dx,offset erms20        ; I'm not sure if things will
  194.     int dos                ; work with only a cassette.
  195.     mov drives,0            ; Say there aren't any drives.
  196.     ret
  197. DODISK    ENDP
  198.  
  199. ; show the definition of a key.  The terminal argument block (which contains
  200. ; the address and length of the definition tables) is passed in ax.
  201. ; Returns a string to print in AX, length of same in CX.
  202. ; Returns normally.
  203. showkey    proc    near
  204.     push    es
  205.     push    ax        ; save the ptr
  206.     mov    bx,ds
  207.     mov    es,bx        ; address data segment
  208.     cld
  209. showk1:    xor    ah,ah
  210.     int    keyb        ; read a char
  211.     push    ax        ; save the character
  212.     call    gss        ; get shift state
  213.     pop    bx
  214.     mov    ah,al        ; shift state to ah
  215.     mov    al,bh        ; scan code to al
  216.     push    ax        ; remember scan code
  217.     mov    di,offset shkbuf
  218.     mov    si,offset shkmsg
  219.     mov    cx,shkmln
  220.     rep    movsb        ; copy in initial message
  221.     call    nout        ; write out scan code
  222.     mov    si,offset shkms1
  223.     mov    cx,shkm1ln    ; second message
  224.     rep    movsb
  225.     pop    ax        ; get scan code back
  226.     pop    bx        ; and terminal arg block
  227.     mov    cx,[bx].klen    ; and length
  228.     jcxz    showk2        ; no table, not defined
  229.     push    di        ; remember output ptr
  230.     mov    di,[bx].ktab    ; get key table
  231.     repne    scasw        ; search for a definition for this
  232.     mov    si,di        ; remember result ptr
  233.     pop    di        ; get output ptr back
  234.     jne    showk2        ; not defined, forget it
  235.     sub    si,[bx].ktab    ; compute offset from beginning
  236.     sub    si,2        ; minus 2 for pre-increment
  237.     add    si,[bx].krpl    ; get index into replacement table
  238.     mov    si,[si]        ; pick up replacement
  239.     mov    cl,[si]        ; get length
  240.     mov    ch,0
  241.     inc    si
  242.     rep    movsb        ; copy into buffer
  243. showk2:    mov    ax,offset shkbuf ; this is buffer
  244.     mov    cx,di
  245.     sub    cx,ax        ; length
  246.     pop    es
  247.     ret            ; and return
  248. showkey    endp
  249.  
  250. ; Clear the input buffer. This throws away all the characters in the
  251. ; serial interrupt buffer.  This is particularly important when
  252. ; talking to servers, since NAKs can accumulate in the buffer.
  253. ; Returns normally.
  254.  
  255. CLRBUF    PROC    NEAR
  256.     cli
  257.     mov ax,offset source
  258.     mov srcpnt,ax
  259.     mov savesi,ax
  260.     mov count,0
  261.     sti
  262.     ret
  263. CLRBUF    ENDP
  264.  
  265. ; Clear to the end of the current line.  Returns normally.
  266.  
  267. CLEARL    PROC    NEAR
  268.     mov ah,3        ; Clear to end of line.
  269.     mov bh,0
  270.     int bios        ; Get current cursor position
  271.     mov cx,dx
  272.     mov dl,79
  273.     mov ah,7
  274.     mov al,0
  275.     mov bh,7
  276.     int bios
  277.     ret
  278. CLEARL    ENDP
  279.  
  280. ; Put the char in AH to the serial port.  This assumes the
  281. ; port has been initialized.  Should honor xon/xoff.  Skip returns on
  282. ; success, returns normally if the character cannot be written.
  283.  
  284. outchr:    mov bp,portval
  285.     cmp ds:[bp].floflg,0    ; Are we doing flow control.
  286.     je outch2        ; No, just continue.
  287.     mov cl,trans.rtime    ; receive timeout interval
  288.     mov ch,0
  289. outch1:    cmp xofrcv,true        ; Are we being held?
  290.     jne outch2        ; No - it's OK to go on.
  291.     mov al,1        ; else sleep for a second
  292.     call sleep
  293.     loop outch1        ; and try it again
  294.     mov xofrcv,false    ; timed out, force it off and fall thru.
  295. outch2:    push dx            ; Save register.
  296.     sub cx,cx
  297.     mov al,ah        ; Parity routine works on AL.
  298.     call dopar        ; Set parity appropriately.
  299.     mov ah,al        ; Don't overwrite character with status.
  300.     mov dx,modem.mdstat    ; Get port status.
  301. outch3:    in al,dx
  302.     test al,20H        ; Transmitter ready?
  303.     jnz outch4        ; Yes
  304.     loop outch3
  305.      jmp outch5        ; Timeout
  306. outch4:    mov al,ah        ; Now send it out
  307.     mov dx,modem.mddat
  308.     out dx,al
  309.     pop dx
  310.     jmp rskp
  311. outch5:    pop dx
  312.     ret
  313.  
  314. ; This routine blanks the screen.  Returns normally.
  315.  
  316. CMBLNK    PROC    NEAR        ; This is stolen from the IBM example.
  317.     mov cx,0
  318.     mov dx,184FH
  319.     mov bh,7
  320.     mov ax,600H
  321.     int bios
  322.     ret
  323. CMBLNK  ENDP
  324.  
  325. ; Locate: homes the cursor.  Returns normally.
  326.  
  327. LOCATE  PROC    NEAR
  328.     mov dx,0        ; Go to top left corner of screen.
  329.     jmp poscur
  330. LOCATE  ENDP
  331.  
  332. ; write a line in inverse video at the bottom of the screen...
  333. ; the line is passed in dx, terminated by a $.  Returns normally.
  334. putmod    proc    near
  335.     push    dx        ; preserve message
  336.     mov    cx,1800h
  337.     mov    dx,184fh
  338.     mov    ax,600h        ; scroll to clear the line
  339.     mov    bh,70h        ; inverse video
  340.     int    bios
  341.     mov    dx,1800h    ; now address line 24
  342.     call    poscur
  343.     pop    si        ; get message back
  344. putmo1:    lodsb            ; get a byte
  345.     cmp    al,'$'        ; end of string?
  346.     je    putmo2
  347.     mov    ah,14        ; write to screen
  348.     mov    bx,07000h    ; inverse video, page one
  349.     int    bios
  350.     jmp    putmo1
  351. putmo2:    ret            ; and return
  352. putmod    endp
  353.  
  354. ; clear the mode line written by putmod.  Returns normally.
  355. clrmod    proc    near
  356.     mov    cx,1800h
  357.     mov    dx,184fh
  358.     mov    ax,600h
  359.     mov    bh,7h
  360.     int    bios
  361.     ret
  362. clrmod    endp
  363.  
  364. ; put a help message on the screen.  This one uses reverse video...
  365. ; pass the message in ax, terminated by a null.  Returns normally.
  366. puthlp    proc    near
  367.     push    ax        ; preserve this
  368.     mov    si,ax        ; point to it
  369.     mov    dh,1        ; init counter
  370. puthl1:    lodsb            ; get a byte
  371.     cmp    al,lf        ; linefeed?
  372.     jne    puthl2        ; no, keep going
  373.     inc    dh        ; count it
  374.     jmp    puthl1        ; and keep looping
  375. puthl2:    cmp    al,0        ; end of string?
  376.     jne    puthl1        ; no, keep going
  377.     mov    ax,600h        ; scroll to clear window
  378.     xor    cx,cx        ; from top left
  379.     mov    dl,4fh        ; to bottom right of needed piece
  380.     mov    bh,70h        ; inverse video
  381.     int    bios
  382.     call    locate        ; home cursor
  383.     pop    si        ; point to string again
  384. puthl3:    lodsb            ; get a byte
  385.     cmp    al,0        ; end of string?
  386.     je    puthl4        ; yes, stop
  387.     mov    ah,14
  388.     int    bios        ; else write to screen
  389.     jmp    puthl3        ; and keep going
  390. puthl4:    mov    dx,24 * 100H    ; go to last line
  391.     jmp    poscur        ; position and return
  392. puthlp    endp
  393.  
  394. ; Set the baud rate for the current port, based on the value
  395. ; in the portinfo structure.  Returns normally.
  396.  
  397. DOBAUD    PROC    NEAR
  398.     mov bp,portval
  399.     mov temp1,ax        ; Don't overwrite previous rate. [25]
  400.     mov ax,ds:[bp].baud    ; Check if new rate is valid. [25]
  401.     mov tmp,2
  402.     mul tmp            ; Get index into baud table.
  403.     mov bx,offset bddat    ; Start of table.
  404.     add bx,ax
  405.     mov ax,[bx]        ; The data to output to port.
  406.     cmp ax,0FFH        ; Unimplemented baud rate.
  407.     jne dobd0
  408.     mov ax,temp1        ; Get back orginal value.
  409.     mov ds:[bp].baud,ax    ; Leave baud rate as is.
  410.     mov ah,prstr
  411.     mov dx,offset badbd    ; Give an error message.
  412.     int dos
  413.     ret
  414. dobd0:    mov temp1,ax        ; Remember value to output. [25]
  415.     mov dx,modem.mdcom    ; LCR -- Initialize baud rate. [19b]
  416.     in al,dx
  417.     mov bl,al
  418.     or ax,80H
  419.     out dx,al
  420.     mov dx,modem.mddat    ; [19b]
  421.     mov ax,temp1
  422.     out dx,al
  423.     inc dx
  424.     mov al,ah
  425.     out dx,al
  426.     mov dx,modem.mdcom    ; [19b]
  427.     mov al,bl
  428.     out dx,al
  429.     ret
  430. DOBAUD    ENDP
  431.  
  432. ; Get the current baud rate from the serial card and set it
  433. ; in the portinfo structure for the current port.  Returns normally.
  434. ; This is used during initialization.
  435.  
  436. GETBAUD    PROC    NEAR
  437.     mov dx,modem.mdcom    ; Get current Line Control Register value.
  438.     in al,dx
  439.     mov bl,al        ; Save it.
  440.     or ax,80H        ; Turn on to access baud rate generator.
  441.     out dx,al
  442.     mov dx,modem.mddat    ; Divisor latch.
  443.     inc dx
  444.     in al,dx        ; Get hi order byte.
  445.     mov ah,al        ; Save here.
  446.     dec dx
  447.     in al,dx        ; Get lo order byte.
  448.     push ax    
  449.     mov dx,modem.mdcom
  450.     mov al,bl        ; Restore old value.
  451.     out dx,al
  452.     pop ax
  453.     cmp ax,0FFFFH        ; Who knows what this is.
  454.     je getb2
  455.     mov bx,offset bddat    ; Find rate's offset into table.
  456.     mov cl,0        ; Keep track of index.
  457. getb0:    cmp ax,[bx]
  458.     je getb1
  459.     inc cl
  460.     cmp cl,baudsiz        ; At the end of the list.
  461.     jge getb2
  462.     add bx,2
  463.     jmp getb0
  464. getb1:    mov ch,0
  465.     mov bp,portval
  466.     mov ds:[bp].baud,cx    ; Set baud rate.
  467.     ret
  468. getb2:    mov ah,prstr
  469.     mov dx,offset erms40
  470.     int dos
  471.     ret
  472. GETBAUD    ENDP
  473.  
  474. ; skip returns if no character available at port,
  475. ; otherwise returns with char in al, # of chars in buffer in dx.
  476. PRTCHR  PROC    NEAR
  477.     call chkxon        ; see if we need to xon
  478.     cmp count,0
  479.     jnz prtch2
  480.     jmp rskp        ; No data - check console.
  481. prtch2:    mov si,savesi
  482.     lodsb            ; get a byte
  483.     cmp si,offset source + bufsiz    ; bigger than buffer?
  484.     jb prtch1        ; no, keep going
  485.     mov si,offset source    ; yes, wrap around
  486. prtch1:    dec count
  487.     mov savesi,si 
  488.     mov dx,count        ; return # of chars in buffer
  489.     ret
  490. PRTCHR  ENDP
  491.  
  492. ; local routine to see if we have to transmit an xon
  493. chkxon    proc    near
  494.     push    bx
  495.     mov    bx,portval
  496.     cmp    [bx].floflg,0    ; doing flow control?
  497.     je    chkxo1        ; no, skip all this
  498.     cmp    xofsnt,false    ; have we sent an xoff?
  499.     je    chkxo1        ; no, forget it
  500.     cmp    count,mntrgh    ; below trigger?
  501.     jae    chkxo1        ; no, forget it
  502.     mov    ax,[bx].flowc    ; ah gets xon
  503.     call    outchr        ; send it
  504.     nop
  505.     nop
  506.     nop            ; in case it skips
  507.     mov    xofsnt,false    ; remember we've sent the xon.
  508. chkxo1:    pop    bx        ; restore register
  509.     ret            ; and return
  510. chkxon    endp
  511.  
  512. ; Send a break out the current serial port.  Returns normally.
  513. SENDBR    PROC    NEAR
  514.     push cx
  515.     push dx
  516.     push ax
  517.     xor cx,cx        ; Clear loop counter.
  518.     mov dx,brkadr        ; Port address.  [19b]
  519.     in al,dx        ; Get current setting.
  520.     or al,brkval        ; Set send-break bit(s).
  521.     out dx,al        ; Start the break.
  522.     push ax
  523.     mov ax,275        ; # of ms to wait
  524.     call pcwait        ; hold break for desired interval
  525.     pop ax
  526.     xor al,brkval        ; Clear send-break bit(s).
  527.     out dx,al        ; Stop the break.
  528.     pop ax
  529.     pop dx
  530.     pop cx
  531.     ret            ; And return.
  532. SENDBR    ENDP
  533.  
  534. ; Wait for the # of milliseconds in ax
  535. ; Thanks to Bernie Eiben for this one.
  536. pcwait    proc    near
  537.     mov    cx,240        ; inner loop counter for 1 millisecond
  538. pcwai1:    sub    cx,1        ; inner loop takes 20 clock cycles
  539.     jnz    pcwai1
  540.     dec    ax        ; outer loop counter
  541.     jnz    pcwait        ; wait another millisecond
  542.     ret
  543. pcwait    endp
  544.  
  545. ; Position the cursor according to contents of DX:
  546. ; DH contains row, DL contains column.  Returns normally.
  547.  
  548. POSCUR    PROC    NEAR
  549.     mov ah,2        ; Position cursor.
  550.     mov bh,0
  551.     int bios
  552.     ret
  553. POSCUR    ENDP
  554.  
  555. ; Delete a character from the terminal.  This works by printing
  556. ; backspaces and spaces.  Returns normally.
  557.  
  558. DODEL    PROC    NEAR
  559.     mov ah,prstr
  560.     mov dx,offset delstr    ; Erase weird character.
  561.     int dos            
  562.     ret
  563. DODEL    ENDP
  564.  
  565. ; Move the cursor to the left margin, then clear to end of line.
  566. ; Returns normally.
  567.  
  568. CTLU    PROC    NEAR
  569.     mov ah,prstr
  570.     mov dx,offset clrlin
  571.     int dos
  572.     call clearl
  573.     ret
  574. CTLU    ENDP
  575.  
  576. ; set the current port.  
  577.  
  578. COMS    PROC    NEAR
  579.     mov dx,offset comptab
  580.     mov bx,0
  581.     mov ah,cmkey
  582.     call comnd
  583.      jmp r
  584.     push bx
  585.     mov ah,cmcfm
  586.     call comnd        ; Get a confirm.
  587.      jmp comx        ;  Didn't get a confirm.
  588.      nop
  589.     pop bx
  590.     mov flags.comflg,bl    ; Set the comm port flag.
  591.     cmp flags.comflg,1    ; Using Com 1?
  592.     jne coms0        ; Nope.
  593.     mov ax,offset port1
  594.     mov portval,ax
  595.     mov modem.mddat,MDMDAT1    ; Set COM1 defaults.
  596.     mov modem.mdstat,MDMSTS1
  597.     mov modem.mdcom,MDMCOM1
  598.     mov modem.mddis,MDMINTC
  599.     mov modem.mden,MDMINTO
  600.     mov modem.mdmeoi,EOICOM
  601.     mov modem.mdintv,MDMINTV
  602.     mov brkadr,MDMCOM1
  603.     ret
  604. coms0:    mov ax,offset port2
  605.     mov portval,ax
  606.     mov modem.mddat,MDMDAT2    ; Set COM2 defaults.
  607.     mov modem.mdstat,MDMSTS2
  608.     mov modem.mdcom,MDMCOM2
  609.     mov modem.mddis,MDINTC2
  610.     mov modem.mden,MDINTO2
  611.     mov modem.mdmeoi,EOICOM2
  612.     mov modem.mdintv,MDINTV2
  613.     mov brkadr,MDMCOM2
  614.     ret
  615. comx:    pop bx
  616.     ret
  617. COMS    ENDP
  618.  
  619. ; Set heath emulation on/off.
  620.  
  621. VTS    PROC    NEAR
  622.     mov dx,offset ontab
  623.     mov bx,0
  624.     mov ah,cmkey
  625.     call comnd
  626.      jmp r
  627.     push bx
  628.     mov ah,cmcfm
  629.     call comnd        ; Get a confirm.
  630.      jmp vt0        ;  Didn't get a confirm.
  631.      nop
  632.     pop bx
  633.     mov flags.vtflg,bl    ; Set the VT52 emulation flag.
  634.     ret
  635. vt0:    pop bx
  636.     ret
  637. VTS    ENDP
  638.  
  639. ; initialization for using serial port.  This routine performs
  640. ; any initialization necessary for using the serial port, including
  641. ; setting up interrupt routines, setting buffer pointers, etc.
  642. ; Doing this twice in a row should be harmless (this version checks
  643. ; a flag and returns if initialization has already been done).
  644. ; SERRST below should restore any interrupt vectors that this changes.
  645. ; Returns normally.
  646.  
  647. SERINI    PROC    NEAR
  648.     push es
  649.     cmp portin,0        ; Did we initialize port already? [21c]
  650.     jne serin0        ; Yes, so just leave. [21c]
  651.     cli            ; Disable interrupts
  652.     cld            ; Do increments in string operations
  653.     xor ax,ax        ; Address low memory
  654.     mov es,ax
  655.     mov bx,modem.mdintv    ; Save serial card interrupt vector. [19b]
  656.     mov ax,es:[bx]
  657.     mov savsci,ax
  658.     mov ax,offset serint    ; And point it to my routine
  659.     mov es:[bx],ax
  660.     add bx,2        ; Save CS register too. [19b]
  661.     mov ax,es:[bx]
  662.     mov savscs,ax
  663.     mov es:[bx],cs
  664.     mov portin,1        ; Remember port has been initialize. 
  665.     call clrbuf        ; Clear input buffer. 
  666.     mov ax,modem.mdstat
  667.     mov mst,ax        ; Use this address for status. 
  668.     mov ax,modem.mddat
  669.     mov mdat,ax        ; Use this address for data. 
  670.     mov al,modem.mdmeoi
  671.     mov mdeoi,al        ; Use to signify end-of-interrupt. 
  672.     in al,21H        ; Set up 8259 interrupt controller
  673.     and al,modem.mden    ; Enable INT3 or INT4. 
  674.     out 21H,al
  675.     mov dx,modem.mdcom    ; Set up the serial card. 
  676.     mov al,3
  677.     out dx,al
  678.     mov dl,0F9H
  679.     mov al,1        ; Set up interrupt enable register
  680.     out dx,al
  681.     mov dl,0FCH        ; Enable interrupts from serial card
  682.     mov al,0BH
  683.     out dx,al
  684.     sti            ; Allow interrupts
  685.     mov dl,0F8H
  686.     in al,dx
  687. serin0:    pop es
  688.     ret            ; We're done.
  689. SERINI    ENDP
  690.  
  691. ; Reset the serial port.  This is the opposite of serini.  Calling
  692. ; this twice without intervening calls to serini should be harmless.
  693. ; Returns normally.
  694.  
  695. SERRST    PROC    NEAR
  696.     push es            ; preserve this
  697.     cmp portin,0        ; Reset already? 
  698.     je srst1        ; Yes, just leave. 
  699.     cli            ; Disable interrupts
  700.     mov dx,03FCH        ; Disable modem interrupts
  701.     cmp flags.comflg,1    ; Using port 1 ? 
  702.     je srst0        ; Yes - continue. 
  703.     mov dh,02        ; Set for port 2. 
  704. srst0:    mov al,3
  705.     out dx,al
  706.     in al,21H        ; Interrupt controller
  707.     or al,modem.mddis    ; Inhibit IRQ3 or IRQ4. 
  708.     out 21H,al
  709.     xor bx,bx        ; Address low memory
  710.     mov es,bx
  711.     mov bx,modem.mdintv    ; Restore the serial card int vector 
  712.     mov ax,savsci
  713.     mov es:[bx],ax
  714.     add bx,2        ; Restore CS too. 
  715.     mov ax,savscs
  716.     mov es:[bx],ax
  717.     mov portin,0        ; Reset flag.
  718.     sti
  719. srst1:    pop es
  720.     ret            ; All done.
  721. SERRST    ENDP
  722.  
  723. ; serial port interrupt routine.  This is not accessible outside this
  724. ; module, handles serial port receiver interrupts.
  725.  
  726. SERINT  PROC  NEAR
  727.     push bx
  728.     push dx
  729.     push ax
  730.     push es
  731.     push di
  732.     push ds
  733.     push bp
  734.     push cx
  735.     cld
  736.     mov ax,seg datas
  737.     mov ds,ax        ; address data segment
  738.     mov es,ax
  739.     mov di,srcpnt        ; Registers for storing data.
  740.     mov dx,mst        ; Asynch status port. [19b]
  741.     in al,dx
  742.     test al,mdminp        ; Data available?
  743.     jz retint        ; Nope.
  744.     mov dx,mdat        ; [19b]
  745.     in al,dx
  746.     cmp telflg,0        ; File transfer or terminal mode? [17c]
  747.     jz srint0
  748.     and al,7FH        ; Terminal mode (7 bits only). 
  749. srint0: or al,al
  750.     jz retint        ; Ignore nulls.
  751.     mov ah,al
  752.     and ah,7fH        ; strip parity temporarily
  753.     cmp ah,7FH        ; Ignore rubouts, too.
  754.     jz retint
  755.     mov bp,portval
  756.     cmp ds:[bp].floflg,0    ; Doing flow control?
  757.     je srint2        ; Nope.
  758.     mov bx,ds:[bp].flowc    ; Flow control char (BH = XON, BL = XOFF).
  759.     cmp al,bl        ; Is it an XOFF?
  760.     jne srint1        ; Nope, go on.
  761.     mov xofrcv,true        ; Set the flag.
  762.     jmp retint
  763. srint1:    cmp al,bh        ; Get an XON?
  764.     jne srint2        ; No, go on.
  765.     mov xofrcv,false    ; Clear our flag.
  766.     jmp retint
  767. srint2:    stosb
  768.     cmp di,offset source + bufsiz
  769.     jb srint3        ; not past end...
  770.     mov di,offset source    ; wrap buffer around
  771. srint3:    inc count
  772.     cmp ds:[bp].floflg,0    ; Doing flow control?
  773.     je retint        ; No, just leave.
  774.     cmp xofsnt,true        ; Have we sent an XOFF?
  775.     je retint        ; Yes.
  776.     cmp count,mntrgh    ; Past the high trigger point?
  777.     jbe retint        ; No, we're within our limit.
  778.     mov ah,bl        ; Get the XOFF.
  779.     call outchr        ; Send it.
  780.     nop
  781.     nop
  782.     nop            ; ignore failure.
  783.     mov xofsnt,true        ; Remember we sent it.
  784. retint:    mov srcpnt,di
  785.     sti
  786.     mov al,mdeoi        ; [19b]
  787.     out intcon1,al        ; Send End-of-Interrupt to 8259.
  788.     pop cx
  789.     pop bp
  790.     pop ds
  791.     pop di
  792.     pop es
  793.     pop ax
  794.     pop dx
  795.     pop bx
  796. intret:    iret
  797. SERINT    ENDP
  798.  
  799. ; Produce a short beep.  The PC DOS bell is long enough to cause a loss
  800. ; of data at the port.  Returns normally.
  801.  
  802. BEEP    PROC    NEAR
  803.     mov al,10110110B    ; Gen a short beep (long one losses data.)
  804.     out timer+3,al        ; Code snarfed from Technical Reference.
  805.     mov ax,533H
  806.     out timer+2,al
  807.     mov al,ah
  808.     out timer+2,al
  809.     in al,port_b
  810.     mov ah,al
  811.     or al,03
  812.     out port_b,al
  813.     sub cx,cx
  814.     mov bl,1
  815. beep0:  loop beep0
  816.     dec bl        
  817.     jnz beep0
  818.     mov al,ah
  819.     out port_b,al
  820.     ret
  821. BEEP    ENDP 
  822.  
  823. ; put the number in ax into the buffer pointed to by di.  Di is updated
  824. nout    proc    near
  825.     mov    dx,0        ; high order is always 0.
  826.     mov    bx,10
  827.     div    bx        ; divide to get digit
  828.     push    dx        ; save remainder digit
  829.     or    ax,ax        ; test quotient
  830.     jz    nout1        ; zero, no more of number
  831.     call    nout        ; else call for rest of number
  832. nout1:    pop    ax        ; get digit back
  833.     add    al,'0'        ; make printable
  834.     stosb            ; drop it off
  835.     ret            ; and return
  836. nout    endp
  837.  
  838. ; Jumping to this location is like retskp.  It assumes the instruction
  839. ;   after the call is a jmp addr.
  840.  
  841. RSKP    PROC    NEAR
  842.     pop bp
  843.     add bp,3
  844.     push bp
  845.     ret
  846. RSKP    ENDP
  847.  
  848. ; Jumping here is the same as a ret.
  849.  
  850. R    PROC    NEAR
  851.     ret
  852. R    ENDP
  853.  
  854. code    ends 
  855.     end
  856.